package com.example.websocket;

import com.example.pojo.DeviceAttribute;
import com.example.service.DeviceService;
import com.example.utils.Authentication;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
public class DeviceWebSocketHandler extends TextWebSocketHandler {

    private static final Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>();
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private DeviceService deviceService;

    @Override
    public void afterConnectionEstablished(WebSocketSession session) {
        sessions.put(session.getId(), session);
        System.out.println("WebSocket连接已建立: " + session.getId());
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        // 解析前端发送的消息
        String payload = message.getPayload();
        Map<String, Object> requestData = objectMapper.readValue(payload, Map.class);

        String action = (String) requestData.get("action");

        // 根据不同的action处理
        if ("getDeviceState".equals(action)) {
            sendDeviceState(session);
        } else if ("getDeviceAttribute".equals(action)) {
            sendDeviceAttribute(session);
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        sessions.remove(session.getId());
        log.info("WebSocket连接已关闭: {}", session.getId());
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        log.error("WebSocket连接出错: " + session.getId() + ", 错误: " + exception.getMessage());
        sessions.remove(session.getId());
    }

    // 发送设备状态
    private void sendDeviceState(WebSocketSession session) throws Exception {
        log.info("WebSocket发送设备状态");
        Map<String, Object> response = new ConcurrentHashMap<>();
        response.put("type", "deviceState");
        response.put("data", getDeviceStateData());

        String json = objectMapper.writeValueAsString(response);
        session.sendMessage(new TextMessage(json));
    }

    // 发送设备属性
    private void sendDeviceAttribute(WebSocketSession session) throws Exception {
        log.info("WebSocket发送设备属性");
        Map<String, Object> response = new ConcurrentHashMap<>();
        response.put("type", "deviceAttribute");
        response.put("data", getDeviceAttributeData());

        String json = objectMapper.writeValueAsString(response);
        session.sendMessage(new TextMessage(json));
    }

    // 获取设备状态数据
    private Integer getDeviceStateData() throws Exception {
        return deviceService.getDeviceOnlineStatus(Authentication.getToken());
    }

    // 获取设备属性数据
    private DeviceAttribute getDeviceAttributeData() throws Exception {
        return deviceService.getAttribute(Authentication.getToken());
    }

    // 定时推送设备状态更新
    public void broadcastDeviceState() {
        sessions.values().forEach(session -> {
            try {
                if (session.isOpen()) {
                    sendDeviceState(session);
                }
            } catch (Exception e) {
                log.error("推送设备状态失败: " + e.getMessage());
            }
        });
    }

    // 定时推送设备属性更新
    public void broadcastDeviceAttribute() {
        sessions.values().forEach(session -> {
            try {
                if (session.isOpen()) {
                    sendDeviceAttribute(session);
                }
            } catch (Exception e) {
                log.error("推送设备属性失败: " + e.getMessage());
            }
        });
    }
}
